﻿using AutoMapper;
using DFGK.IRepository;
using DFGK.IService;
using DFGK_WMS.Model.Dto;
using DFGK_WMS.Model.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Yitter.IdGenerator;

namespace DFGK.Service
{
    public class CellService : BaseService, ICellService
    {
        private readonly IWarehouseRepository _warehouseRepository;
        private readonly IAreaRepository _areaRepository;
        private readonly IShelfRepository _shelfRepository;
        private readonly ICellRepository _cellRepository;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IDictItemRepository _dictItemRepository;
        private readonly IRoutewayRepository _routewayRepository;
        public CellService(IMapper mapper, ICellRepository _cellRepository, IWarehouseRepository warehouseRepository, IAreaRepository areaRepository, IShelfRepository shelfRepository, IDictItemRepository _dictItemRepository, IUnitOfWork unitOfWork, IRoutewayRepository routewayRepository) : base(mapper)
        {
            this._cellRepository = _cellRepository;
            this._dictItemRepository = _dictItemRepository;
            _warehouseRepository = warehouseRepository;
            _areaRepository = areaRepository;
            _shelfRepository = shelfRepository;
            _unitOfWork = unitOfWork;
            _routewayRepository = routewayRepository;
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool AddCell(Cell obj, out string message)
        {
            message = string.Empty;
            var cobj = _cellRepository.QueryIsEntityWhere(x => x.Code == obj.Code);
            if (cobj != null)
            {
                message = "编码已存在！";
                return false;
            }
            if (obj.WhId == null)
            {
                message = "请选择库房！";
                return false;
            }
            //库房
            var wobj = _warehouseRepository.QueryEntityById((long)obj.WhId);
            if (wobj != null && wobj.Status == 1)
            {
                obj.WhName = wobj.Name;
                obj.WhCode = wobj.Code;
            }
            else
            {
                message = "库房不存在或已被禁用！";
                return false;
            }
            if (obj.AreaId == null)
            {
                message = "请选择库区！";
                return false;
            }
            //库区
            var aobj = _areaRepository.QueryEntityById((long)obj.AreaId);
            if (aobj != null && aobj.Status == 1)
            {
                obj.AreaName = aobj.Name;
                obj.AreaCode = aobj.Code;
            }
            else
            {
                message = "库区不存在或已被禁用！";
                return false;
            }
            if (obj.ShelfId == null)
            {
                message = "请选择货架！";
                return false;
            }
            //货架
            var sobj = _shelfRepository.QueryEntityById((long)obj.ShelfId);
            if (sobj != null && sobj.Status == 1)
            {
                obj.ShelfCode = sobj.Code;
                obj.ShelfName = sobj.Name;
                obj.RoutewayId = sobj.RoutewayId.GetValueOrDefault();
            }
            else
            {
                message = "货架不存在或已被禁用！";
                return false;
            }
            obj.DistanceValue = Convert.ToDecimal(Math.Sqrt(Math.Pow(obj.LayerNo, 2) + Math.Pow(obj.ColumnNo, 2) + Math.Pow(obj.LineNo - 1, 2)));

            _cellRepository.AddEntity(obj);
            return _unitOfWork.SaveChangesEntity();
        }

        public bool AddCell(IEnumerable<Cell> obj)
        {
            _cellRepository.AddEntityList(obj.ToList());
            return _unitOfWork.SaveChangesEntity();
        }
        /// <summary>
        /// 批量添加仓位
        /// </summary>
        /// <param name="cellCreateBodyDTO"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool BatchCreateCell(CellCreateBodyDTO cellCreateBodyDTO, out string message)
        {
            message = "";
            List<Cell> cellList = new List<Cell>();
            var warehouse = _warehouseRepository.QueryIsEntityWhere(w => w.Id == cellCreateBodyDTO.WhId && w.Status == 1);
            if (warehouse == null)
            {
                message = "库房不存在或已被禁用！";
                return false;
            }
            var area = _areaRepository.QueryIsEntityWhere(a => a.Id == cellCreateBodyDTO.AreaId && a.Status == 1);
            if (area == null)
            {
                message = "库区不存在或已被禁用";
                return false;
            }
            List<Shelf> shelves = _shelfRepository.GetEntityWhereAll(s => s.WhId == cellCreateBodyDTO.WhId && s.AreaId == cellCreateBodyDTO.AreaId && s.Status == 1 && cellCreateBodyDTO.ShelfIds.Contains(s.Id)).ToList();
            if (shelves == null || shelves.Count == 0)
            {
                message = "货架不存在或已被禁用";
                return false;
            }
            var rlist = _routewayRepository.GetEntityAlls();
            foreach (var shelf in shelves)
            {
                int? rouway = rlist.FirstOrDefault(x => x.Id == shelf.RoutewayId)?.DisplayOrder;
                if (rouway <= 0 || rouway == null)
                {
                    message = "巷道信息有误！";
                    return false;
                }

                int maxDepth = shelf.Depth.GetValueOrDefault();
                string columnNum = "";
                string layerNum = "";
                for (int layerIndex = 1; layerIndex <= cellCreateBodyDTO.MaxLayer; layerIndex++)
                {
                    if (layerIndex < 10)
                    {
                        layerNum = "0" + layerIndex;
                    }
                    else
                    {
                        layerNum = layerIndex.ToString();
                    }
                    for (int columnIndex = 1; columnIndex <= cellCreateBodyDTO.MaxColumn; columnIndex++)
                    {
                        bool isMaxDepth = false;
                        if (shelf.Number == 1 || shelf.Number == 9)
                        {
                            isMaxDepth = true;
                        }

                        if (columnIndex < 10)
                        {
                            columnNum = "0" + columnIndex;
                        }
                        else
                        {
                            columnNum = columnIndex.ToString();
                        }
                        
                        string name = string.Format("{0}排{1}列{2}层", shelf.Code, columnNum, layerNum);
                        string cellCode = string.Format("{0}{1}{2}", shelf.Code, columnNum, layerNum);

                        Cell cell = new Cell
                        {
                            Id = YitIdHelper.NextId(),
                            Code = cellCode,
                            Name = name,
                            WhId = warehouse.Id,
                            WhName = warehouse.Name,
                            AreaId = area.Id,
                            AreaName = area.Name,
                            LineNo = shelf.Number.GetValueOrDefault(), //排号就是每一个货架号
                            LayerNo = layerIndex,
                            ColumnNo = columnIndex,
                            DepthIndex = (int)shelf.Depth,
                            IsLock = false,
                            Status = 1,
                            IsMaxDepth = isMaxDepth,
                            FullStatus = 0,
                            BusinessType = 0,
                            RoutewayId = shelf.RoutewayId.GetValueOrDefault(),
                            CreateDate = DateTime.Now,
                            ShelfId = shelf.Id,
                            ShelfCode = shelf.Code,
                            ShelfName = shelf.Name,
                            CellType = 1,
                            DistanceValue = Convert.ToDecimal(Math.Sqrt(Math.Pow(layerIndex, 2) + Math.Pow(columnIndex, 2) + Math.Pow(layerIndex - 1, 2))),
                            HeightType = 1,
                            AreaCode = area.Code,
                            WhCode = warehouse.Code,
                        };
                        cellList.Add(cell);
                    }
                }
            }
            if (cellList == null || cellList.Count == 0)
            {
                return false;
            }
            _cellRepository.AddEntityList(cellList);
            if (_unitOfWork.SaveChangesEntity())
            {
                _unitOfWork.CommitChanges();
                return true;
            }
            _unitOfWork.RollbackChanges();
            return false;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool DelCell(long id)
        {
            var cobj = _cellRepository.QueryEntityById(id);
            if (cobj != null)
            {
                _cellRepository.DelEntity(cobj);
                return _unitOfWork.SaveChangesEntity();
            }
            return false;
        }

        public List<Cell> GetAllCellList()
        {
            return _cellRepository.GetAllEntityList();
        }

        public Cell? GetCellById(long id)
        {
            return _cellRepository.QueryEntityById(id);
        }

        /// <summary>
        /// 仓位统计
        /// </summary>
        /// <returns></returns>
        public CellStatisticsDto GetCellCount()
        {
            CellStatisticsDto celllist = new CellStatisticsDto();
            var cells = _cellRepository.GetEntityAlls();
            celllist.CellLock = cells.Where(x => x.Status == 2).Count().ToString();
            celllist.CellReserve = cells.Where(x => x.FullStatus == 0 && x.IsLock == false && x.BusinessType == 0 && x.Status == 1).Count().ToString();
            celllist.CellCount = cells.Count().ToString();
            celllist.CellUseCount = cells.Where(x => x.FullStatus == 1).Count().ToString();
            celllist.CellVacancyCount = cells.Where(x => x.FullStatus == 0).Count().ToString();
            return celllist;
        }

        public List<Cell> GetCellList(string? logicalPartCode, int fullStatus, int status, string? cname, long whid, long areid, long sheid, int pageIndex, int pageSize, out int totalCount)
        {
            var clist = _cellRepository.GetEntityAlls();
            //逻辑分区
            if (!string.IsNullOrEmpty(logicalPartCode))
            {
                clist = clist.Where(x => x.LogicalPartCode == logicalPartCode);
            }
            //仓位状态
            if (fullStatus < 3)
            {
                clist = clist.Where(x => x.FullStatus == fullStatus);
            }
            //状态
            if (status < 8)
            {
                clist = clist.Where(x => x.Status == status);
            }
            //仓位名称
            if (!string.IsNullOrEmpty(cname))
            {
                clist = clist.Where(x => x.Name.Contains(cname));
            }
            //库房
            if (whid != 0)
            {
                clist = clist.Where(x => x.WhId == whid);
            }
            //库区
            if (areid != 0)
            {
                clist = clist.Where(x => x.AreaId == areid);
            }
            //货架
            if (sheid != 0)
            {
                clist = clist.Where(x => x.ShelfId == sheid);
            }
            var list = _cellRepository.GetEntityAlls(clist, pageIndex, pageSize, out totalCount, x => x.CreateDate, false);
            return list.ToList();
        }

        /// <summary>
        /// 仓位左侧树形显示
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public List<Menuitem> GetMenuitem()
        {
            var wlist = _warehouseRepository.GetAllEntityList();

            return wlist.Select(item => new Menuitem
            {
                label = item.Name,
                value = item.Id,
                icon = item.Code,
                alias = "wh",
                children = GetAreaMenuitem(item.Id)
            }).ToList();
        }
        public List<Menuitem> GetAreaMenuitem(long wid)
        {
            var list = _areaRepository.GetEntityWhereAll(x => x.WhId == wid).ToList();
            return list.Select(x => new Menuitem
            {
                label = x.Name,
                value = x.Id,
                icon = x.Code,
                alias = "area",
                children = GetShelfMenuitem(x.Id)
            }).ToList();
        }
        public List<Menuitem> GetShelfMenuitem(long aid)
        {
            var list = _shelfRepository.GetEntityWhereAll(x => x.AreaId == aid);
            return list.Select(x => new Menuitem
            {
                label = x.Name,
                value = x.Id,
                icon = x.Code,
                alias = "shelf",
                children = null
            }).ToList();
        }

        /// <summary>
        /// 修改仓位
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool UpdCell(Cell obj, out string message)
        {
            message = string.Empty;
            var cobj = _cellRepository.QueryIsEntityWhere(x => x.Id != obj.Id && x.Code == obj.Code);
            if (cobj != null)
            {
                message = "编码已存在！";
                return false;
            }

            //库房
            var wobj = _warehouseRepository.QueryEntityById((long)obj.WhId);
            if (wobj != null && wobj.Status == 1)
            {
                obj.WhName = wobj.Name;
                obj.WhCode = wobj.Code;
            }
            else
            {
                message = "库房不存在或已被禁用！";
                return false;
            }
            if (obj.AreaId == null)
            {
                message = "请选择库区！";
                return false;
            }
            //库区
            var aobj = _areaRepository.QueryEntityById((long)obj.AreaId);
            if (aobj != null && aobj.Status == 1)
            {
                obj.AreaName = aobj.Name;
                obj.AreaCode = aobj.Code;
            }
            else
            {
                message = "库区不存在或已被禁用！";
                return false;
            }
            if (obj.ShelfId == null)
            {
                message = "请选择货架！";
                return false;
            }
            //货架
            var sobj = _shelfRepository.QueryEntityById((long)obj.ShelfId);
            if (sobj != null && sobj.Status == 1)
            {
                obj.ShelfCode = sobj.Code;
                obj.ShelfName = sobj.Name;
                obj.RoutewayId = sobj.RoutewayId.GetValueOrDefault();
            }
            else
            {
                message = "货架不存在或已被禁用！";
                return false;
            }
            obj.DistanceValue = Convert.ToDecimal(Math.Sqrt(Math.Pow(obj.LayerNo, 2) + Math.Pow(obj.ColumnNo, 2) + Math.Pow(obj.LineNo - 1, 2)));

            _cellRepository.UpdEntity(obj);
            return _unitOfWork.SaveChangesEntity();
        }

        public List<Cell> GetTransferBinToCellList(string arecode)
        {

            List<Cell> list = new List<Cell>();
            var clist = _cellRepository.GetEntityWhereAll(c => c.IsMaxDepth == true).ToList();
            if (!clist.Any())
            {
                return list;
            }
            //查询可用的最深仓位
            var AvailableCell = clist.Where(c => c.Status == 1 && c.IsLock == false && c.BusinessType == 0 && c.FullStatus == 0);
            //将可用的最深仓位添加到集合当中
            list.AddRange(AvailableCell); 
            //不可用的最深仓位
            var NoAvailableCell = clist.Where(c => c.Status != 1 || c.IsLock != false || c.BusinessType != 0 || c.FullStatus != 0);
            if (!NoAvailableCell.Any())
            {
                return list;
            }
            foreach ( var item in NoAvailableCell)
            {
                var depthCell = item.LineNo > 4 ? _cellRepository.GetEntityWhereAll(c => c.LayerNo == item.LayerNo && c.ColumnNo == item.ColumnNo && c.LineNo < item.LineNo && c.LineNo > 4).OrderByDescending(c => c.DepthIndex).ToList() : _cellRepository.GetEntityWhereAll(c => c.LayerNo == item.LayerNo && c.ColumnNo == item.ColumnNo && c.LineNo > item.LineNo && c.LineNo < 4).OrderByDescending(c => c.DepthIndex).ToList();
                if (depthCell.Count() <= 0)
                {
                    continue;
                }
                //循环当前深位最深的其他仓位 有里往外去寻找可用的仓位 避免深位无货而浅位有货的状况
                foreach (var dcell in depthCell)
                {
                    if (dcell.Status == 1 && dcell.IsDel == false && dcell.BusinessType == 0 && dcell.FullStatus == 0)
                    {
                        list.Add(dcell);//找到仓位就跳出循环开始下一个
                        break;
                    }
                }
            }
            return list;
        }

        public Cell? GetCellByCode(string code)
        {
            var cobj = _cellRepository.QueryIsEntityWhere(x => x.Code == code);
            return cobj;
        }

        public string GetErpCodeByCode(string code)
        {
            var cobj = GetCellByCode(code);
            if (cobj == null) return string.Empty;
            return cobj.Erpcode;
        }

        public List<string> GetErpCodeByCodeList(string[] code)
        {
            var list = new List<string>();
            foreach (var item in code)
            {
                var res = GetCellByCode(item);
                if (res == null) list.Add(string.Empty);
                else list.Add(res.Erpcode);
            }
            return list;
        }


        public List<dynamic> GetCellByLayers(params int[] layers)
        {
            var list = new List<dynamic>();

            foreach (var item in layers)
            {
                list.Add(new { Layer = item, Cells = _cellRepository.GetEntityAll().Where(t => t.LayerNo == item).ToList() });
            }
            return list;
        }

        public List<Cell> GetCellByLayer(int layer)
        {
            var clist = _cellRepository.GetEntityWhereAll(x => x.LayerNo == layer);

            return clist.ToList();
        }
    }
}
